package murraco.service;

import javax.servlet.http.HttpServletRequest;

import murraco.common.ResultCode;
import murraco.constants.UserConstants;
import murraco.dto.UserDataDTO;
import murraco.dto.UserResponseDTO;
import murraco.exception.BusinessException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import murraco.model.User;
import murraco.repository.UserRepository;
import murraco.security.JwtTokenProvider;

@Service
public class UserService {

  @Autowired
  private UserRepository userRepository;

  @Autowired
  private PasswordEncoder passwordEncoder;

  @Autowired
  private JwtTokenProvider jwtTokenProvider;

  @Autowired
  private AuthenticationManager authenticationManager;

  public UserResponseDTO signin(String username, String password) {
    try {
        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        String token = jwtTokenProvider.createToken(username, userRepository.findByLoginCode(username).getRoles());
        User user = userRepository.findByLoginCode(username);
        UserResponseDTO userResponseDTO = new UserResponseDTO();
        BeanUtils.copyProperties(user,userResponseDTO);
        userResponseDTO.setToken(token);

        return userResponseDTO;
    } catch (AuthenticationException e) {
      throw new BusinessException( ResultCode.USER_LOGIN_ERROR);
    }
  }

  public String signup(User user) {
    if (!userRepository.existsByLoginCode(user.getLoginCode())) {
      user.setPassword(passwordEncoder.encode(user.getPassword()));
      user.setBorrowStatus(UserConstants.unBorrowed);
      userRepository.save(user);
      return jwtTokenProvider.createToken(user.getLoginCode(), user.getRoles());
    } else {
      throw new BusinessException( ResultCode.USER_HAS_EXISTED);
    }
  }

  public void delete(String username) {
    userRepository.deleteByLoginCode(username);
  }

  public User search(String username) {
    User user = userRepository.findByLoginCode(username);
    if (user == null) {
      throw new BusinessException(ResultCode.USER_NOT_EXIST);
    }
    return user;
  }

  public User whoami(HttpServletRequest req) {
    return userRepository.findByLoginCode(jwtTokenProvider.getUsername(jwtTokenProvider.resolveToken(req)));
  }

  public String refresh(String username) {
    return jwtTokenProvider.createToken(username, userRepository.findByLoginCode(username).getRoles());
  }

  public String updatePassword(UserDataDTO userDataDTO){
      User user = userRepository.findByLoginCode(userDataDTO.getLoginCode());
      user.setPassword(passwordEncoder.encode(userDataDTO.getPassword()));
      userRepository.save(user);
      return userDataDTO.getPassword();
  }

  public UserDataDTO updateinfo(UserDataDTO userDataDTO){
        User user = userRepository.findByLoginCode(userDataDTO.getLoginCode());
        user.setName(userDataDTO.getName());
        user.setPhone(userDataDTO.getPhone());
        userRepository.save(user);
        return userDataDTO;
    }

  public void borrowBicycle(String userId,String bicycleNum){
      User user = userRepository.findByLoginCode(userId);
      user.setBicycleNum(bicycleNum);
      user.setBorrowStatus(UserConstants.borrowed);
      userRepository.save(user);
  }

    public void returnBicycle(String userId){
        User user = userRepository.findByLoginCode(userId);
        user.setBicycleNum("");
        user.setBorrowStatus(UserConstants.unBorrowed);
        userRepository.save(user);
    }

}
